home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / pc / files / t_unix / j109lxa4.tar / nrs.c < prev    next >
C/C++ Source or Header  |  1994-06-04  |  5KB  |  227 lines

  1. /* This module implements the serial line framing method used by
  2.  * net/rom nodes.  This allows the net/rom software to talk to
  3.  * an actual net/rom over its serial interface, which is useful
  4.  * if we want to do packet switching for multi-line wormholes.
  5.  * Copyright 1989 Dan Frank, W9NK
  6.  */
  7. #include <stdio.h>
  8. #include "global.h"
  9. #include "config.h"
  10. #include "mbuf.h"
  11. #include "iface.h"
  12. #include "pktdrvr.h"
  13. #include "ax25.h"
  14. #include "nrs.h"
  15. #include "asy.h"
  16. #include "trace.h"
  17. #include "commands.h"
  18.  
  19. #ifdef NRS
  20.  
  21. static struct mbuf *nrs_encode __ARGS((struct mbuf *bp));
  22. static struct mbuf *nrs_decode __ARGS((int dev,char c));
  23.  
  24. /* control structures, sort of overlayed on async control blocks */
  25. struct nrs Nrs[ASY_MAX];
  26.  
  27. /* Send a raw net/rom serial frame */
  28. int
  29. nrs_raw(iface,bp)
  30. struct iface *iface;
  31. struct mbuf *bp;
  32. {
  33.     struct mbuf *bp1;
  34.  
  35.     dump(iface,IF_TRACE_OUT,CL_AX25,bp);
  36.     iface->rawsndcnt++;
  37.     iface->lastsent = secclock();
  38.  
  39.     if((bp1 = nrs_encode(bp)) == NULLBUF){
  40.         free_p(bp);
  41.         return -1;
  42.     }
  43.     return Nrs[iface->xdev].send(iface->dev,bp1);
  44. }
  45.  
  46. /* Encode a packet in net/rom serial format */
  47. static struct mbuf *
  48. nrs_encode(bp)
  49. struct mbuf *bp;
  50. {
  51.     struct mbuf *lbp;    /* Mbuf containing line-ready packet */
  52.     register char *cp;
  53.     int c;
  54.     unsigned char csum = 0;
  55.  
  56.     /* Allocate output mbuf that's twice as long as the packet.
  57.      * This is a worst-case guess (consider a packet full of STX's!)
  58.      * Add five bytes for STX, ETX, checksum, and two nulls.
  59.      */
  60.     lbp = alloc_mbuf((int16)(2*len_p(bp) + 5));
  61.     if(lbp == NULLBUF){
  62.         /* No space; drop */
  63.         free_p(bp);
  64.         return NULLBUF;
  65.     }
  66.     cp = lbp->data;
  67.  
  68.     *cp++ = STX;
  69.  
  70.     /* Copy input to output, escaping special characters */
  71.     while((c = PULLCHAR(&bp)) != -1){
  72.         switch(c){
  73.         case STX:
  74.         case ETX:
  75.         case DLE:
  76.             *cp++ = DLE;
  77.             /* notice drop through to default */
  78.         default:
  79.             *cp++ = c;
  80.         }
  81.         csum += c;
  82.     }
  83.     *cp++ = ETX;
  84.     *cp++ = csum;
  85.     *cp++ = NUL;
  86.     *cp++ = NUL;
  87.     
  88.     lbp->cnt = cp - lbp->data;
  89.     return lbp;
  90. }
  91. /* Process incoming bytes in net/rom serial format
  92.  * When a buffer is complete, return it; otherwise NULLBUF
  93.  */
  94. static struct mbuf *
  95. nrs_decode(dev,c)
  96. int dev;    /* net/rom unit number */
  97. char c;        /* Incoming character */
  98. {
  99.     struct mbuf *bp;
  100.     register struct nrs *sp;
  101.  
  102.     sp = &Nrs[dev];
  103.     switch(sp->state) {
  104.         case NRS_INTER:
  105.             if(uchar(c) == STX) {    /* look for start of frame */
  106.                 sp->state = NRS_INPACK;    /* we're in a packet */
  107.                 sp->csum = 0;                /* reset checksum */
  108.             }
  109.             return NULLBUF;
  110.         case NRS_CSUM:
  111.             bp = sp->rbp;
  112.             sp->rbp = NULLBUF;
  113.             sp->rcnt = 0;
  114.             sp->state = NRS_INTER;    /* go back to inter-packet state */
  115.             if(sp->csum == uchar(c)) {
  116.                 sp->packets++;
  117.             } else {
  118.                 free_p(bp);    /* drop packet with bad checksum */
  119.                 bp = NULLBUF;
  120.                 sp->errors++;    /* increment error count */
  121.             }
  122.             return bp;
  123.         case NRS_ESCAPE:
  124.             sp->state = NRS_INPACK;    /* end of escape */
  125.             break;            /* this will drop through to char processing */
  126.         case NRS_INPACK:
  127.             switch(uchar(c)) {
  128.             /* If we see an STX in a packet, assume that previous */
  129.             /* packet was trashed, and start a new packet */
  130.             case STX:
  131.                 free_p(sp->rbp);
  132.                 sp->rbp = NULLBUF;
  133.                 sp->rcnt = 0;
  134.                 sp->csum = 0;
  135.                 sp->errors++;
  136.                 return NULLBUF;
  137.             case ETX:
  138.                 sp->state = NRS_CSUM;    /* look for checksum */
  139.                 return NULLBUF;
  140.             case DLE:
  141.                 sp->state = NRS_ESCAPE;
  142.                 return NULLBUF;
  143.             }
  144.     }
  145.     /* If we get to here, it's with a character that's part of the packet.
  146.      * Make sure there's space for it.
  147.      */
  148.     if(sp->rbp == NULLBUF){
  149.         /* Allocate first mbuf for new packet */
  150.         if((sp->rbp1 = sp->rbp = alloc_mbuf(NRS_ALLOC)) == NULLBUF) {
  151.             sp->state = NRS_INTER;
  152.             return NULLBUF; /* No memory, drop */
  153.         }
  154.         sp->rcp = sp->rbp->data;
  155.     } else if(sp->rbp1->cnt == NRS_ALLOC){
  156.         /* Current mbuf is full; link in another */
  157.         if((sp->rbp1->next = alloc_mbuf(NRS_ALLOC)) == NULLBUF){
  158.             /* No memory, drop whole thing */
  159.             free_p(sp->rbp);
  160.             sp->rbp = NULLBUF;
  161.             sp->rcnt = 0;
  162.             sp->state = NRS_INTER;
  163.             return NULLBUF;
  164.         }
  165.         sp->rbp1 = sp->rbp1->next;
  166.         sp->rcp = sp->rbp1->data;
  167.     }
  168.     /* Store the character, increment fragment and total
  169.      * byte counts
  170.      */
  171.     *sp->rcp++ = c;
  172.     sp->rbp1->cnt++;
  173.     sp->rcnt++;
  174.     sp->csum += uchar(c);    /* add to checksum */
  175.     return NULLBUF;
  176. }
  177.  
  178. /* Process net/rom serial line I/O */
  179. void
  180. nrs_recv(dev,v1,v2)
  181. int dev;
  182. void *v1;
  183. void *v2;
  184. {
  185.     char c;
  186.     struct mbuf *bp,*nbp;
  187.     struct phdr phdr;
  188.  
  189.     /* Process any pending input */
  190.     for(;;){
  191.         c = Nrs[dev].get(Nrs[dev].iface->dev);
  192.         if((bp = nrs_decode(dev,c)) == NULLBUF)
  193.             continue;
  194.         if((nbp = pushdown(bp,sizeof(phdr))) == NULLBUF){
  195.             free_p(bp);
  196.             continue;
  197.         }
  198.         phdr.iface = Nrs[dev].iface;
  199.         phdr.type = CL_AX25;
  200.         memcpy(&nbp->data[0],(char *)&phdr,sizeof(phdr));
  201.         enqueue(&Hopper,nbp);
  202.     }
  203.  
  204. }
  205. /* donrstat:  display status of active net/rom serial interfaces */
  206. int
  207. donrstat(argc,argv,p)
  208. int argc;
  209. char *argv[];
  210. void *p;
  211. {
  212.     register struct nrs *np;
  213.     register int i;
  214.  
  215.     tprintf("Interface   RcvB  NumReceived  CSumErrors\n");
  216.  
  217.     for(i = 0, np = Nrs; i < ASY_MAX ; i++, np++)
  218.         if(np->iface != NULLIF)
  219.             if(tprintf(" %8s   %4d   %10lu  %10lu\n",
  220.              np->iface->name, np->rcnt,
  221.              np->packets, np->errors) == EOF)
  222.                 break;
  223.  
  224.     return 0;
  225. }
  226. #endif
  227.